#include <jni.h>
#include <string>
#include "log.h"
#include "gif_lib.h"
#include "android/bitmap.h"

extern "C" {
void drawFrameActual(GifFileType *gifFileType, void *pixel);
}

#define argb(a, r, g, b) ( ((a) & 0xff) << 24 ) | ( ((b) &0xff) << 16 ) | ( ((g) & 0xff) << 8 ) | ((r) & 0xff)

typedef struct Userdata {
    int count;
    int current;
    int *delays;
} Userdata;

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_mygif_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {

    LOGI("%s", "hello world");
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}extern "C"
JNIEXPORT jlong JNICALL
Java_com_example_mygif_GifHandler_nativeLoadFile(JNIEnv *env, jobject thiz, jstring path) {

    const char *file = env->GetStringUTFChars(path, nullptr);
    int error;
    GifFileType *gifFileType = DGifOpenFileName(file, &error);
    DGifSlurp(gifFileType);
    LOGI("width :%d", gifFileType->SWidth);
    LOGI("height :%d", gifFileType->SHeight);
    int count = gifFileType->ImageCount;
    auto *userdata = static_cast<Userdata *>(malloc(sizeof(Userdata)));
    memset(userdata, 0, sizeof(Userdata));
    userdata->delays = (int *) malloc(sizeof(int) * count);
    memset(userdata->delays, 0, count);
    userdata->count = count;

    //在图形控制扩展块中的第5个字节和第6个字节存放的是每帧的延迟时间，单位是
    // 1/100秒，而唯一能标识这是一个图形扩展块的是第2个字节，固定值0xF9
    ExtensionBlock *extensionBlock;
    //给gibBean的delays赋值，它将存放所有的帧的延迟时间
    for (int i = 0; i < gifFileType->ImageCount; i++) {
        //取出每一帧
        SavedImage frame = gifFileType->SavedImages[i];
        // Count of extensions before imag
        //遍历扩展块，取出图形扩展块的表示的时间
        for (int j = 0; j < frame.ExtensionBlockCount; j++) {
            //#define GRAPHICS_EXT_FUNC_CODE    0xf9    /* graphics control (GIF89) */
            if (GRAPHICS_EXT_FUNC_CODE == frame.ExtensionBlocks[j].Function) {
                extensionBlock = &frame.ExtensionBlocks[j];
                break;
            }
        }
        if (extensionBlock) {
            int delay = 10 * ((extensionBlock->Bytes[2] << 8) | extensionBlock->Bytes[1]);
            userdata->delays[i] = delay;
        }
    }

    gifFileType->UserData = userdata;

    env->ReleaseStringUTFChars(path, file);

    return (jlong) (gifFileType);
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_mygif_GifHandler_nativeGetWidth(JNIEnv *env, jobject thiz, jlong pointer) {
    //将指针转换为GifByteType的指针
    GifFileType *gifFileType = reinterpret_cast<GifFileType *>(pointer);

    return gifFileType->SWidth;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_mygif_GifHandler_nativeGetHeight(JNIEnv *env, jobject thiz, jlong pointer) {
    //将指针转换为GifByteType的指针
    GifFileType *gifFileType = reinterpret_cast<GifFileType *>(pointer);
    return gifFileType->SHeight;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_mygif_GifHandler_nativeDrawFrame(JNIEnv *env, jobject thiz, jobject bitmap,
                                                  jlong pointer) {
    //将指针转换为GifByteType的指针
    GifFileType *gifFileType = reinterpret_cast<GifFileType *>(pointer);

    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, bitmap, &info);
    LOGI("info width %d", info.width);
    LOGI("info height %d", info.height);
    //锁定内存
    void *pixel;
    AndroidBitmap_lockPixels(env, bitmap, &pixel);

    drawFrameActual(gifFileType, pixel);
    //释放内存
    AndroidBitmap_unlockPixels(env, bitmap);
    auto *userdata = static_cast<Userdata *>(gifFileType->UserData);
    if (userdata->current == userdata->count - 1) {
        userdata->current = 0;
    } else {
        userdata->current++;
    }
    return userdata->delays[userdata->current];
}

void drawFrameActual(GifFileType *gifFileType, void *pixel) {

    //获取当前帧
    auto *userdata = static_cast<Userdata *>(gifFileType->UserData);
    LOGI("current frame is %d", userdata->current);
    SavedImage savedImage = gifFileType->SavedImages[userdata->current];
    //图像信息
    GifImageDesc gifImageDesc = savedImage.ImageDesc;
    ColorMapObject *colorMapObject = gifImageDesc.ColorMap;
    if (colorMapObject == nullptr) {
        colorMapObject = gifFileType->SColorMap;
    }

    GifWord *colors = (int *) pixel;

    GifWord width = gifImageDesc.Width;
    GifWord height = gifImageDesc.Height;
    GifWord top = gifImageDesc.Top;
    GifWord left;

    //遍历图像像素点
    for (GifWord i = top; i < top + height; ++i) {

        left = i * width;
        for (GifWord j = left; j < left + width; j++) {
            GifByteType gifByteType = savedImage.RasterBits[j];
            GifColorType gifColorType = colorMapObject->Colors[gifByteType];
            GifWord color = argb(0XFF, gifColorType.Red, gifColorType.Green, gifColorType.Blue);
            colors[j] = color;
        }
    }
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_mygif_GifHandler_test(JNIEnv *env, jobject thiz) {

}extern "C"
JNIEXPORT void JNICALL
Java_com_example_mygif_GifHandler_testBitmap(JNIEnv *env, jobject thiz, jobject bitmap) {

    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, bitmap, &info);
    int w = info.width;
    int h = info.height;
    void *addrPtr;
    AndroidBitmap_lockPixels(env, bitmap, &addrPtr);

    auto *pixel = (int *) addrPtr;
    int left = 0;
    for (int i = 0; i < h; i++) {
        left = i * w;
        for (int j = left; j < left + w; j++) {

            pixel[j] = argb(0XFF, 0, 0, 0);
//            LOGI("%d::  %x\n",j,pixel[j]);
        }
    }

    AndroidBitmap_unlockPixels(env, bitmap);
}